package org.dawfinn.droiditarian;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import org.dawfinn.droiditarian.server.Geohash;
import org.dawfinn.droiditarian.server.data.DeedLocation;
import org.dawfinn.droiditarian.server.data.PMF;

import com.google.appengine.api.datastore.Key;

@SuppressWarnings("unchecked")
public class DeedLocationQuery {

	public static List<DeedLocation> getDeedLocations(int size) {
		PersistenceManager pm = PMF.get().getPersistenceManager();

		Query query = pm.newQuery(DeedLocation.class);
		query.setOrdering("completedDate desc");
		query.setRange(0, size);

		List<DeedLocation> results = (List<DeedLocation>) query.execute();
		List<DeedLocation> reversedResults = prepareResults(pm, results);

		query.closeAll();
		pm.close();

		return reversedResults;
	}

	public static List<DeedLocation> getDeedLocations(int size, float minLat,
			float minLng, float maxLat, float maxLng) {
		PersistenceManager pm = PMF.get().getPersistenceManager();

		Geohash gh = Geohash.getInstance();

		String northWestGeohash = gh.encode(maxLat, maxLng);
		String southEastGeohash = gh.encode(minLat, minLng);

		Query query = pm.newQuery(DeedLocation.class);
		// geohash values seem to grow from south-east to north-west
		// the first order by parameter must be the same one with inequalities
		// so, just get the past week's worth of good deeds instead of sorting
		long currentDay = new Date().getTime()
				/ DeedLocation.MILLISECONDS_PER_DAY;
		String queryString = "geohash < \"" + northWestGeohash
				+ "\" && geohash > \"" + southEastGeohash + "\" && (";
		for (int i = 0; i < 7; i++) {
			queryString += "days == " + (currentDay - i);
			if (i < 6)
				queryString += " || ";
		}
		queryString += ")";
		query.setFilter(queryString);
		query.setOrdering("geohash asc, days desc");
		query.setRange(0, size);

		List<DeedLocation> results = (List<DeedLocation>) query.execute();
		List<DeedLocation> reversedResults = prepareResults(pm, results);

		query.closeAll();
		pm.close();

		return reversedResults;
	}

	private static List<DeedLocation> prepareResults(PersistenceManager pm,
			List<DeedLocation> results) {

		// Can't modify query results, so make a new modifiable list to reverse
		List<DeedLocation> reversedResults = new ArrayList<DeedLocation>(
				results.size());
		
		// Transaction transaction = pm.currentTransaction();
		// transaction.begin();
		for (int index = results.size() - 1; index >= 0; index--) {
			DeedLocation result = results.get(index);
			// if (result.getTimesQueried() == null) {
			// result.setTimesQueried(1);
			// } else {
			// result.setTimesQueried(result.getTimesQueried() + 1);
			// }
			reversedResults.add(result);
//			double[] latlng = Geohash.getInstance().decode(result.getGeohash());
//			System.out.println("Geohash: " + result.getGeohash() + " Lat: "
//					+ latlng[Geohash.LAT] + " Lng: " + latlng[Geohash.LNG]);
		}
		// transaction.commit();
		return reversedResults;
	}

	public static DeedLocation findByKey(Key deedKey) {
		PersistenceManager pm = PMF.get().getPersistenceManager();

		Query q = pm.newQuery(DeedLocation.class);
		q.setFilter("key == keyParam");
		q.declareParameters("com.google.appengine.api.datastore.Key keyParam");

		List<DeedLocation> results = (List<DeedLocation>) q.execute(deedKey);
		assert results.size() == 1; // sanity check

		DeedLocation theDeed = results.get(0); // eager fetch

		q.closeAll();
		pm.close();

		return theDeed;
	}

}
